﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Threading;
using System.Windows.Automation;

namespace Compiled_Tests
{
    public class MouseEvents
    {
        #region Mouse Attributes
        private const UInt32 MouseEventMove = 0x0001;
        private const UInt32 MouseEventLeftDown = 0x0002;
        private const UInt32 MouseEventLeftUp = 0x0004;
        private const UInt32 MouseEventRightDown = 0x0008;
        private const UInt32 MouseEventRightUp = 0x0010;
        private const UInt32 MouseEventMiddleDown = 0x0020;
        private const UInt32 MouseEventMiddleUp = 0x0040;
        private const UInt32 MouseEventXDown = 0x0080;
        private const UInt32 MouseEventXUp = 0x0100;
        private const UInt32 MouseEventWheel = 0x0800;
        private const UInt32 MouseEventVirtualDesk = 0x4000;
        private const UInt32 MouseEventAbsolute = 0x8000;

        private static bool locker;
        
        private static uint dx = 0;
        private static uint dy = 0;
        #endregion

        #region User32 Imports
        [DllImport("user32.dll")]
        private static extern void mouse_event(UInt32 dwFlags, UInt32 dx, UInt32 dy, UInt32 dwData, IntPtr dwExtraInfo);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SetCursorPos(int X, int Y);
        #endregion

        #region Custom Mouse Events

        private static object Lock = new Object();

        private static void RectMiddle(AutomationElement ae)
        {
            int x = (int)(ae.Current.BoundingRectangle.Left + (ae.Current.BoundingRectangle.Width / 2));
            int y = (int)(ae.Current.BoundingRectangle.Top + (ae.Current.BoundingRectangle.Height / 2));
            dx = (uint)x;
            dy = (uint)y;
            SetCursorPos(x, y);
            Thread.Sleep(500);
        }

        public static void LeftDown(AutomationElement ae)
        {
            lock(Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventLeftDown,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void LeftUp(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventLeftUp,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void LeftClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventLeftDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventLeftUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void LeftDoubleClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventLeftDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventLeftUp, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventLeftDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventLeftUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void LeftClickDrag(AutomationElement source, AutomationElement target)
        {
            LeftDown(source);
            Thread.Sleep(500);
            LeftUp(target);
            dx = dy = 0;
        }

        public static void RightDown(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventRightDown,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void RightUp(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventRightUp,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void RightClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventRightDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventRightUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void RightDoubleClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventRightDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventRightUp, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventRightDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventRightUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void RightClickDrag(AutomationElement source, AutomationElement target)
        {
            RightDown(source);
            Thread.Sleep(500);
            RightUp(target);
            dx = dy = 0;
        }

        public static void MiddleDown(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventMiddleDown,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void MiddleUp(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventMiddleUp,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void MiddleClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventMiddleDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventMiddleUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void XDown(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventXDown,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void XUp(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                mouse_event(MouseEventXUp,  dx, dy, 0, new IntPtr());
                dx = dy = 0;
                locker = false;
            }
        }

        public static void XClick(AutomationElement ae)
        {
            RectMiddle(ae);
            mouse_event(MouseEventXDown, dx, dy, 0, new IntPtr());
            mouse_event(MouseEventXUp, dx, dy, 0, new IntPtr());
            dx = dy = 0;
        }

        public static void MoveMouseTo(AutomationElement ae)
        {
            lock (Lock)
            {
                RectMiddle(ae);
                dx = dy = 0;
                locker = false;
            }
        }

        #endregion
    }
}
